home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / mail / mh / vmail / vmail.2of3 / init.c < prev    next >
C/C++ Source or Header  |  1991-04-05  |  11KB  |  471 lines

  1. #ifndef lint
  2. static char *RCS_init_c = "$Id: init.c,v 1.3 90/04/23 14:41:11 rogers Exp $";
  3. #endif
  4.  
  5. /* --------------------
  6.     vmail -- init.c
  7.  
  8.     Initialisation routines - setting ttystate, finding valid folders,
  9.     trapping signals.
  10.  
  11.     Ttystate is controlled by a mix of curses and ioctl.  For simplicity,
  12.     initial setups are done with curses.  Curses is also used for basic
  13.     screen manipulation.  However, for speed ioctl is used in switching
  14.     in and out of normal terminal state.
  15.  
  16.     Copyright (C) J. Zobel, University of Melbourne, October 1987.
  17. -------------------- */
  18.  
  19. #include "defs.h"
  20. #include <signal.h>
  21.  
  22. static struct sgttyb tty, t_tty;        /* for holding tty state */
  23. static struct tchars chrs, t_chrs;
  24. static struct ltchars lchrs, t_lchrs;
  25.  
  26. static char    termcap[1024],                /* termcap entry */
  27.             *cur_folder;                /* initial current folder */
  28.  
  29. sig_type    tstp(), tint();
  30.  
  31. /* --------------------
  32.     Start-up routine - set terminal control, signals, etc.
  33. -------------------- */
  34. void
  35. init(argc, argv)
  36.     int        argc;
  37.     char    **argv;
  38. {
  39.     folder    ftmp, find_mail();
  40.     char    *pargv[20],                    /* argv from profile */
  41.             *profile = (char *) NULL,    /* location of MH profile */
  42.             *home = (char *) NULL,        /* home directory */
  43.             *term = (char *) NULL;        /* terminal type */
  44.     int        pargc = 0;                    /* argc from profile */
  45.  
  46.     get_home(&home);
  47.     get_env(&term, &profile, home);
  48.     (void)tgetent(termcap, term);
  49.     cols = tgetnum("co");
  50.         /* lines holds no. of lines for headers, ie "li" less STATUS, TITLE */
  51.     lines = tgetnum("li") - 2;
  52.     (void)ioctl(0, TIOCGETP, (caddr_t)&tty);
  53.     (void)ioctl(0, TIOCGETP, (caddr_t)&chrs);
  54.     (void)ioctl(0, TIOCGETP, (caddr_t)&lchrs);
  55.  
  56.     read_profile(&pargc, pargv, profile, home);
  57.     process_args(pargc, pargv);
  58.     find_folders();
  59.     mark_valid_folders(pargc, pargv);
  60.         /* give precedence to command line args => process second */
  61.     mark_valid_folders(argc, argv);
  62.     for(ftmp=folders ; ftmp != (folder) NULL ;)
  63.         if(ftmp->valid)
  64.             ftmp = find_mail(ftmp, true);
  65.         else
  66.             ftmp = ftmp->next;
  67.     if(curflr->valid == EMPTY) {
  68.         (void)printf("%s: folder empty.\n", curflr->name);
  69.         exit(1);
  70.     }
  71.         /* find last instance of initial folder */
  72.     LAST_OF_NAME(curflr);
  73.     curmail = curflr->mail;
  74.  
  75.     (void)initscr();
  76.     (void)crmode();
  77.     (void)noecho();
  78.     (void)nonl();
  79.  
  80.     (void)signal(SIGTSTP, tstp);
  81.     (void)signal(SIGINT, tint);
  82.  
  83.     (void)ioctl(0, TIOCGETP, (caddr_t)&t_tty);
  84.     (void)ioctl(0, TIOCGETP, (caddr_t)&t_chrs);
  85.     (void)ioctl(0, TIOCGETP, (caddr_t)&t_lchrs);
  86.  
  87.     y = FIRST;
  88.     display_page();
  89. }
  90.  
  91.  
  92. /* --------------------
  93.     Find user name, home directory.
  94. -------------------- */
  95. void
  96. get_home(home)
  97.     char **home;
  98. {
  99.     struct passwd *pwent, *getpwuid();
  100. #ifdef vax
  101.     uid_t getuid();
  102. #endif
  103.  
  104.     pwent = getpwuid((int)getuid());
  105.     *home = NEWSTR(strlen(pwent->pw_dir)+1);
  106.     (void)strcpy(*home, pwent->pw_dir);
  107.     if(access(*home, R_OK | W_OK | X_OK)) {
  108.         (void)printf("%s: no permissions.\n", *home);
  109.         exit(1);
  110.     }
  111.     user = NEWSTR(strlen(pwent->pw_name)+1);
  112.     (void)strcpy(user, pwent->pw_name);
  113. }
  114.  
  115.  
  116. /* --------------------
  117.     Find pager, editor, shell, terminal type, MH profile - defaults are PAGER,
  118.     EDITOR, SHELL, none, PROFILE.  Set by PAGER, EDITOR, SHELL, TERM, MH
  119.     environment variables.
  120. -------------------- */
  121. void
  122. get_env(term, profile, home)
  123.     char **term, **profile, *home;
  124. {
  125.     char    **tmp;
  126.  
  127.     for(tmp = environ ; *tmp != (char *) NULL ; tmp++)
  128.         if(!strncmp("PAGER=", *tmp, 6)) {
  129.             pager = NEWSTR(strlen(*tmp)-4);
  130.             (void)strcpy(pager, *tmp+6);
  131.         } else if(!strncmp("EDITOR=", *tmp, 7)) {
  132.             editor = NEWSTR(strlen(*tmp)-5);
  133.             (void)strcpy(editor, *tmp+7);
  134.         } else if(!strncmp("SHELL=", *tmp, 6)) {
  135.             shell = NEWSTR(strlen(*tmp)-4);
  136.             (void)strcpy(shell, *tmp+6);
  137.         } else if(!strncmp("TERM=", *tmp, 5)) {
  138.             *term = NEWSTR(strlen(*tmp)-3);
  139.             (void)strcpy(*term, *tmp+5);
  140.         } else if(!strncmp("MH=", *tmp, 3)) {
  141.             *profile = NEWSTR(strlen(*tmp)-1);
  142.             (void)strcpy(*profile, *tmp+3);
  143.         }
  144.     if(*term == (char *) NULL) {
  145.         (void)printf("Terminal type unknown\n");
  146.         exit(1);
  147.     }
  148.     if(*profile == (char *) NULL) {
  149.         *profile = NEWSTR(strlen(home)+strlen(PROFILE)+2);
  150.         (void)sprintf(*profile, "%s/%s", home, PROFILE);
  151.     }
  152.     if(pager == (char *) NULL) {
  153.         pager = NEWSTR(strlen(PAGER)+1);
  154.         (void)strcpy(pager, PAGER);
  155.     }
  156.     if(shell == (char *) NULL) {
  157.         shell = NEWSTR(strlen(SHELL)+1);
  158.         (void)strcpy(shell, SHELL);
  159.     }
  160.     if(editor == (char *) NULL) {
  161.         editor = NEWSTR(strlen(EDITOR)+1);
  162.         (void)strcpy(editor, EDITOR);
  163.     }
  164. }
  165.  
  166.  
  167. static char argkeep[LEN];            /* storage for args from profile */
  168.  
  169. /* --------------------
  170.     Find mail directory, current-folder, context, default options.
  171. -------------------- */
  172. void
  173. read_profile(pargc, pargv, profile, home)
  174.     int *pargc;
  175.     char **pargv, *profile, *home;
  176. {
  177.     FILE    *fp, *fopen();
  178.     char    str[LEN], *ptr, iscontext[LEN], *index(), *next_token();
  179.  
  180.     if((fp = fopen(profile, "r")) == (FILE *) NULL) {
  181.         (void)printf("Profile: %s: cannot open.\n", profile);
  182.         exit(1);
  183.     }
  184.     *iscontext = '\0';
  185.     while(fgets(str, LEN, fp) != (char *) NULL) {
  186.             /* get entries from profile */
  187.         if(lstrncmp("context:", str, 8) == 0 && *(ptr=str+8) != '\0') {
  188.             squash(str);
  189.             (void)strcpy(iscontext, str+8);
  190.         } else if(lstrncmp("vmail:", str, 6) == 0 && *(ptr=str+6) != '\0') {
  191.             for( ; *ptr == ' ' || *ptr == '\t' ; ptr++)
  192.                 ;
  193.             *index(ptr, '\n') = '\0';
  194.             (void)strcpy(argkeep, ptr);
  195.             for(ptr=argkeep ; *ptr != '\0' ; ) {
  196.                 pargv[(*pargc)++] = ptr;
  197.                 ptr = next_token(ptr);
  198.             }
  199.         } else if(lstrncmp("path:", str, 5) == 0 && *(ptr=str+5) != '\0') {
  200.             squash(str);
  201.             if(*ptr == '/') {        /* full pathname */
  202.                 mail_dir = NEWSTR(strlen(ptr)+1);
  203.                 (void)strcpy(mail_dir, ptr);
  204.             } else {
  205.                 mail_dir = NEWSTR(strlen(home)+strlen(ptr)+1);
  206.                 (void)sprintf(mail_dir, "%s/%s", home, ptr);
  207.             }
  208.         } else if(lstrncmp("folder-protect:", str, 15) == 0 &&
  209.                                                         *(str+15) != '\0') {
  210.             squash(str);
  211.             folder_protect = atoo(str+15);
  212.         } else if(lstrncmp("current-folder:", str, 15) == 0 &&
  213.                                                         *(str+15) != '\0') {
  214.             squash(str);
  215.             cur_folder = NEWSTR(strlen(str+15)+1);
  216.             (void)strcpy(cur_folder, str);
  217.         }
  218.     }
  219.     (void)fclose(fp);
  220.     if(mail_dir == (char *) NULL) {
  221.         mail_dir = NEWSTR(strlen(home)+strlen(MAILDIR)+2);
  222.         (void)sprintf(mail_dir, "%s/%s", home, str+6);
  223.     }
  224.     if(access(mail_dir, R_OK | W_OK | X_OK)) {
  225.         (void)printf("%s: no permissions.\n", mail_dir);
  226.         exit(1);
  227.     }
  228.     if(*iscontext == '\0')
  229.         (void)strcpy(iscontext, CONTEXT);
  230.     context = NEWSTR(strlen(mail_dir)+strlen(iscontext)+2);
  231.     (void)sprintf(context, "%s/%s", mail_dir, iscontext);
  232.     if(access(context, R_OK | W_OK)) {
  233.         (void)printf("%s: no permissions.\n", context);
  234.         exit(1);
  235.     }
  236.     if(cur_folder == (char *) NULL)
  237.         cur_folder = CURFOL;
  238. }
  239.  
  240.  
  241. /* --------------------
  242.     Squash spaces, tabs, newlines out of given string.
  243. -------------------- */
  244. void
  245. squash(str)
  246.     char    *str;
  247. {
  248.     int        i, j;
  249.  
  250.     for(i=0, j=0 ; (str[j] = str[i]) != '\0' ; i++)
  251.         if(str[j] != ' ' && str[j] != '\t' && str[j] != '\n')
  252.             j++;
  253. }
  254.  
  255.  
  256. /* --------------------
  257.     Mark folders as specified by setenv, command line.  At startup, default
  258.     is for only active folder to be cur_folder.
  259. -------------------- */
  260. void
  261. mark_valid_folders(argc, argv)
  262.     int        argc;
  263.     char    **argv;
  264. {
  265.     char    *name;
  266.     folder    f;
  267.  
  268.     name = cur_folder;
  269.         /* find valid folders - mark all folders from argv as valid */
  270.     for(; argc > 0 ; argc--, argv++)
  271.         if(**argv == '+')                /* startup folder */
  272.             name = (*argv) + 1;
  273.         else if(**argv != '-') {        /* not a flag */
  274.             GOTO_NAME(f, *argv);
  275.             if(f == (folder) NULL)
  276.                 (void)printf("Warning: no such folder as %s\n", *argv);
  277.             else
  278.                 f->valid = true;
  279.         }
  280.     GOTO_NAME(f, name);
  281.     if(f == (folder) NULL) {
  282.         (void)printf("%s does not exist\n", name);
  283.         exit(1);
  284.     }
  285.     f->valid = true;
  286.     curflr = f;
  287. }
  288.  
  289.  
  290. /* --------------------
  291.     Reset terminal, clean up.
  292. -------------------- */
  293. void
  294. to_normal()
  295. {
  296.     move(lines+FIRST-1, 0);
  297.     refresh();
  298.     no_control();
  299.     (void)printf("\n");
  300. }
  301.  
  302.  
  303. /* --------------------
  304.     Reset terminal.
  305. -------------------- */
  306. void
  307. no_control()
  308. {
  309.     int x, y;
  310.     char c;
  311.  
  312. #ifdef STANDOUT_CLEANUP
  313.     /*
  314.      * The following code forces curses to issue a standend if it has
  315.      * one pending.
  316.      */
  317.  
  318.     getyx(stdscr, y, x);
  319.     c = inch() & 0x7f;
  320.     if (c == 'a') {
  321.         addch('b');
  322.     }
  323.     else {
  324.         addch('a');
  325.     }
  326.     move(y, x);
  327.     refresh();
  328.     move(y, x);
  329.     addch(c);
  330.     move(y, x);
  331.     refresh();
  332. #endif
  333.  
  334.     (void)ioctl(0, TIOCSETP, (caddr_t)&tty);
  335.     (void)ioctl(0, TIOCSETP, (caddr_t)&chrs);
  336.     (void)ioctl(0, TIOCSETP, (caddr_t)&lchrs);
  337. }
  338.  
  339.  
  340. /* --------------------
  341.     Set terminal.
  342. -------------------- */
  343. void
  344. to_control()
  345. {
  346.     (void)ioctl(0, TIOCSETP, (caddr_t)&t_tty);
  347.     (void)ioctl(0, TIOCSETP, (caddr_t)&t_chrs);
  348.     (void)ioctl(0, TIOCSETP, (caddr_t)&t_lchrs);
  349. }
  350.  
  351.  
  352. #define    mask(s)    (1 << ((s)-1))
  353.  
  354. /* --------------------
  355.     Trap for ^Z.
  356. -------------------- */
  357. sig_type
  358. tstp()
  359. {
  360.     int        x, y;
  361.  
  362.     getyx(curscr, y, x);
  363.     to_normal();
  364.     fix_mh();
  365.  
  366.     (void)signal(SIGTSTP, SIG_DFL);
  367.     (void)sigsetmask(sigblock(0) &~ mask(SIGTSTP));
  368.     (void)kill(0, SIGTSTP);
  369.     (void)sigblock(mask(SIGTSTP));
  370.     (void)signal(SIGTSTP, tstp);
  371.  
  372.     if(top_level) {
  373.         to_control();
  374.         touchwin(curscr);
  375.         (void)wmove(curscr, y, x);
  376.         (void)wrefresh(curscr);
  377.     }
  378. }
  379.  
  380.  
  381. /* --------------------
  382.     Trap for ^?.
  383. -------------------- */
  384.  
  385. sig_type
  386. tint()
  387. {
  388.     touchwin(stdscr);
  389.     addstatus("-- interrupt --", true);
  390.     longjmp(env, 0);    /* jump to main */
  391. }
  392.  
  393.  
  394. /* --------------------
  395.     Convert an ascii string to octal.
  396. -------------------- */
  397. int
  398. atoo(str)
  399.     char *str;
  400. {
  401.     int        i;
  402.  
  403.     for(; *str < '0' && *str > '7' ; str++)
  404.         ;
  405.     for(i=0 ; *str >= '0' && *str <= '7' ; str++)
  406.         i = i*8 + *str - '0';
  407.     return(i);
  408. }
  409.  
  410.  
  411. /* --------------------
  412.     Update MH environment - context and current mail item of current folder.
  413. -------------------- */
  414. fix_mh()
  415. {
  416.     char str[LEN], buf[20];
  417.  
  418.     update(context, "Current-Folder:", curflr->name, 15);
  419.     (void)sprintf(str, "%s/%s/%s", mail_dir, curflr->name, SEQU);
  420.     (void)sprintf(buf, "%d", curmail->number);
  421.     update(str, "cur:", buf, 4);
  422. }
  423.  
  424.  
  425. /* --------------------
  426.     Update file, replacing line beginning with match of len by "match new".
  427. -------------------- */
  428. update(file, match, new, len)
  429.     char    *file, *match, *new;
  430.     int        len;
  431. {
  432.     FILE    *fp, *tmp, *fopen();
  433.     bool    change = false;
  434.     char    *mktemp(), *fgets();
  435.     char    str[LEN], *name = mktemp("/tmp/vmail.XXXXXX");
  436.  
  437.     if((fp = fopen(file, "r")) == (FILE *) NULL) {
  438.         if((fp = fopen(file, "w+")) == (FILE *) NULL)
  439.             (void)printf("Can't open %s for writing\n", file);
  440.         else {
  441.             (void)fprintf(fp, "%s %s\n", match, new);
  442.             (void)fclose(fp);
  443.         }
  444.     } else {
  445.         if((tmp = fopen(name, "w+")) == (FILE *) NULL)
  446.             (void)printf("Can't open %s\n", file);
  447.         else {
  448.             while(fgets(str, LEN, fp) != (char *) NULL)
  449.                 if(lstrncmp(str, match, len) == 0) {
  450.                     change = true;
  451.                     (void)fprintf(tmp, "%s %s\n", match, new);
  452.                 } else
  453.                     (void)fprintf(tmp, "%s", str);
  454.             if(! change)
  455.                 (void)fprintf(tmp, "%s %s\n", match, new);
  456.             (void)fclose(fp);
  457.             (void)fclose(tmp);
  458.             if((fp = fopen(file, "w+")) == (FILE *) NULL)
  459.                 (void)printf("Can't open %s for writing\n", file);
  460.             else {
  461.                 tmp = fopen(name, "r");
  462.                 while(fgets(str, LEN, tmp) != (char *) NULL)
  463.                     (void)fprintf(fp, "%s", str);
  464.                 (void)fclose(fp);
  465.                 (void)fclose(tmp);
  466.                 (void)unlink(name);
  467.             }
  468.         }
  469.     }
  470. }
  471.